//#define Enable

using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEngine;

namespace CGF
{
    public class TextureCompress : AssetPostprocessor
    {
        //支持填写目录或文件名
        string[] IgnoreList =
        {
            "BEIJ-1"
        };

        //图片导入时自动压缩
        void OnPreprocessTexture()
        {
            TextureImporter importer = (TextureImporter)assetImporter;
            for (int i = 0; i < IgnoreList.Length; i++)
            {
                if (importer.assetPath.Contains(IgnoreList[i])) return;
            }
#if Enable
            Compress(importer, EditorUserBuildSettings.activeBuildTarget);
#endif
        }


        [MenuItem("Assets/贴图压缩")]
        private static void CompressAndroid()
        {
            StartCompress(EditorUserBuildSettings.activeBuildTarget);
        }

        private static void StartCompress(BuildTarget platform)
        {
            Object[] objs = Selection.GetFiltered(typeof(Texture2D), SelectionMode.DeepAssets);
            if (objs.Length == 0)
            {
                EditorUtility.DisplayDialog("提示", "请选择贴图", "确定");
                return;
            }
            for (int i = 0; i < objs.Length; i++)
            {
                Compress(objs[i] as Texture2D, platform);
            }
        }

        private static void StartUnCompress()
        {
            Object[] objs = Selection.GetFiltered(typeof(Texture2D), SelectionMode.DeepAssets);
            if (objs.Length == 0)
            {
                EditorUtility.DisplayDialog("提示", "请选择贴图", "确定");
                return;
            }
            for (int i = 0; i < objs.Length; i++)
            {
                UnCompress(objs[i] as Texture2D);
            }
        }

        private static void Compress(Object texture, BuildTarget platform)
        {
            string path = AssetDatabase.GetAssetPath(texture);
            if (string.IsNullOrEmpty(path))
            {
                EditorUtility.DisplayDialog("提示", "传入的 texture 必须是 Project 窗口下的资源", "确定");
                return;
            }
            TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
            Compress(importer, platform);
            AssetDatabase.ImportAsset(path);
        }

        private static void Compress(TextureImporter importer, BuildTarget platform)
        {
            importer.mipmapEnabled = false;
            importer.mipmapEnabled = false;
            importer.npotScale = TextureImporterNPOTScale.None;
            if (platform == BuildTarget.Android)
            {
                TextureImporterPlatformSettings settings = importer.GetPlatformTextureSettings("Android");
                settings.overridden = true;
                settings.maxTextureSize = 4096;
                settings.allowsAlphaSplitting = false;
                if (!IsMultiOfFour(importer))
                {
                    TextureImporter importerNew = ScaleToMO4(importer);
                    if (importerNew != null)
                    {
                        importer = importerNew;
                    }
                }
                //这里不考虑ETC_RGBA4Crunched的情况，因为某些非透明图即使是4的倍数也无法使用ETC_RGBA4Crunched
                settings.format = TextureImporterFormat.ETC2_RGBA8Crunched;
                settings.compressionQuality = 100;
                importer.SetPlatformTextureSettings(settings);
            }
            else if (platform == BuildTarget.iOS)
            {
                TextureImporterPlatformSettings settings = importer.GetPlatformTextureSettings("iPhone");
                settings.overridden = true;
                bool isPOT = IsPowerOfTwo(importer);
                if (IsAlphaTexture(importer))
                {
                    settings.format = isPOT ? TextureImporterFormat.PVRTC_RGBA4 : TextureImporterFormat.ASTC_4x4;
                }
                else
                {
                    settings.format = isPOT ? TextureImporterFormat.PVRTC_RGB4 : TextureImporterFormat.ASTC_6x6;
                }
                settings.compressionQuality = 100;
                importer.SetPlatformTextureSettings(settings);
            }
            else if (platform == BuildTarget.WebGL)
            {
                TextureImporterPlatformSettings settings = importer.GetPlatformTextureSettings("WebGL");
                settings.overridden = true;
                settings.maxTextureSize = 2048;
                settings.allowsAlphaSplitting = false;
                if (!IsMultiOfFour(importer))
                {
                    TextureImporter importerNew = ScaleToMO4(importer);
                    if (importerNew != null)
                    {
                        importer = importerNew;
                    }
                }
                //这里不考虑ETC_RGBA4Crunched的情况，因为某些非透明图即使是4的倍数也无法使用ETC_RGBA4Crunched
                settings.format = TextureImporterFormat.ETC2_RGBA8Crunched;
                settings.compressionQuality = 100;
                importer.SetPlatformTextureSettings(settings);
            }
        }

        private static void UnCompress(Object texture)
        {
            string path = AssetDatabase.GetAssetPath(texture);
            TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
            importer.mipmapEnabled = false;
            importer.mipmapEnabled = false;
            importer.npotScale = TextureImporterNPOTScale.None;

            //Android
            TextureImporterPlatformSettings settingsAndroid = importer.GetPlatformTextureSettings("Android");
            settingsAndroid.overridden = true;
            settingsAndroid.maxTextureSize = 4096;
            settingsAndroid.allowsAlphaSplitting = false;
            settingsAndroid.format = TextureImporterFormat.RGBA32;
            settingsAndroid.compressionQuality = 100;
            importer.SetPlatformTextureSettings(settingsAndroid);

            //iOS
            TextureImporterPlatformSettings settingsIOS = importer.GetPlatformTextureSettings("iPhone");
            settingsIOS.overridden = true;
            bool isPOT = IsPowerOfTwo(importer);
            settingsIOS.format = TextureImporterFormat.RGBA32;
            settingsIOS.compressionQuality = 100;
            importer.SetPlatformTextureSettings(settingsIOS);

            AssetDatabase.ImportAsset(path);
        }

        //被4整除（Android用）
        private static bool IsMultiOfFour(TextureImporter importer)
        {
            (int width, int height) = GetTextureImporterSize(importer);
            return (width % 4 == 0 && height % 4 == 0);
        }

        //2的整数次幂（iOS用）
        private static bool IsPowerOfTwo(TextureImporter importer)
        {
            (int width, int height) = GetTextureImporterSize(importer);
            return (width == height) && (width > 0) && ((width & (width - 1)) == 0);
        }

        //带透明区域的图片
        private static bool IsAlphaTexture(TextureImporter importer)
        {
            return importer.DoesSourceTextureHaveAlpha();
        }

        //获取导入图片的宽高
        private static (int, int) GetTextureImporterSize(TextureImporter importer)
        {
            if (importer != null)
            {
                object[] args = new object[2];
                MethodInfo mi = typeof(TextureImporter).GetMethod("GetWidthAndHeight", BindingFlags.NonPublic | BindingFlags.Instance);
                mi.Invoke(importer, args);
                return ((int)args[0], (int)args[1]);
            }
            return (0, 0);
        }

        //把图片尺寸强制改成4的倍数
        private static TextureImporter ScaleToMO4(TextureImporter importer)
        {
            if (importer != null)
            {
                object[] args = new object[2];
                MethodInfo mi = typeof(TextureImporter).GetMethod("GetWidthAndHeight", BindingFlags.NonPublic | BindingFlags.Instance);
                mi.Invoke(importer, args);
                int originW = (int)args[0];
                int originH = (int)args[1];
                if (originW % 4 != 0 || originH % 4 != 0)
                {
                    while (originW % 4 != 0)
                    {
                        originW += 1;
                    }
                    while (originH % 4 != 0)
                    {
                        originH += 1;
                    }
                    string path = Application.dataPath.Replace("Assets", "") + importer.assetPath;
                    Texture2D textureOrigin = new Texture2D(0, 0);
                    textureOrigin.LoadImage(File.ReadAllBytes(path));
                    textureOrigin = ScaleTexture(textureOrigin, originW, originH) as Texture2D;
                    if (path.EndsWith(".png"))
                    {
                        File.WriteAllBytes(path, textureOrigin.EncodeToPNG());
                    }
                    else if (path.EndsWith(".jpg"))
                    {
                        File.WriteAllBytes(path, textureOrigin.EncodeToJPG());
                    }
                    TextureImporter newImporter = TextureImporter.GetAtPath(path) as TextureImporter;
                    return newImporter;
                }
            }
            return null;
        }

        private static Texture ScaleTexture(Texture source, int targetWidth, int targetHeight)
        {
            Texture2D source2D = source as Texture2D;
            Texture2D result = new Texture2D(targetWidth, targetHeight, source2D.format, false);
            for (int i = 0; i < result.height; ++i)
            {
                for (int j = 0; j < result.width; ++j)
                {
                    Color newColor = source2D.GetPixelBilinear((float)j / (float)result.width, (float)i / (float)result.height);
                    result.SetPixel(j, i, newColor);
                }
            }
            result.Apply();
            return result;
        }
    }
}